using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;


using Advent.aiDevices;

namespace Advent.Controls
{
    /// <summary>
    /// This control manages a SignalLevel object and all the details required to convert between representations.
    /// </summary>
    public partial class SignalLevelCtrl : UserControl
    {

        private SignalLevel _Level = SignalLevel.InVrms(1);

        /// <summary>
        /// This event is raised whenver the signal level is changed due to user actions.
        /// </summary>
        public event EventHandler SignalLevelChanged;

        public SignalLevelCtrl()
        {
            InitializeComponent();

            // Load each of the possible signal level units
            cbo_Units.Items.Clear();

            foreach (SignalLevel.LevelSpecification X in Enum.GetValues(typeof(SignalLevel.LevelSpecification)))
            {
                cbo_Units.Items.Add(X);
            }
            cbo_Units.SelectedIndex = 0;
        }

        /// <summary>
        /// This method simply raises the SignalLevelChanged event
        /// </summary>
        private void OnChanged()
        {
            if (SignalLevelChanged == null) return;
            SignalLevelChanged(this, EventArgs.Empty);
        }

        private void SignalLevelCtrl_Load(object sender, EventArgs e)
        {
            try
            {

                RefreshControls();

                this.Resize += new EventHandler(SignalLevelCtrl_Resize);
                cbo_Units.SelectedIndexChanged += new EventHandler(cbo_Units_SelectedIndexChanged);
                txt_Level.Validating += new CancelEventHandler(txt_Level_Validating);
                txt_Level.KeyUp += new KeyEventHandler(txt_Level_KeyUp);
                SignalLevelCtrl_Resize(this, EventArgs.Empty);
            }
            catch { }
        }

        void txt_Level_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.KeyCode != Keys.Return) return;
            try
            {
                UpdateLevel();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            finally
            {
                RefreshControls();
            }
        }

        void txt_Level_Validating(object sender, CancelEventArgs e)
        {
            try
            {
                UpdateLevel();
                
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                e.Cancel = true;
            }finally {
                RefreshControls();
            }
        }

        private void UpdateLevel()
        {
            SignalLevel L = Parse();
            if (L != _Level)
            {
                _Level = L;
                OnChanged();
            }
        }


        /// <summary>
        /// This assigns or retrives the current signal level within the control
        /// </summary>
        public SignalLevel Level
        {
            set
            {
                if (value == null) throw new NullReferenceException();
                _Level = value.ToRepresentation((SignalLevel.LevelSpecification) cbo_Units.SelectedItem);
                RefreshControls();
            }
            get
            {
                return _Level;
            }
        }



        /// <summary>
        /// This parses the current contents of the controls and returns the corresponding Signal Level
        /// </summary>
        /// <returns></returns>
        private SignalLevel Parse()
        {
            double Value;
            if (!double.TryParse(txt_Level.Text, out Value)) throw new Exception("Invalid level");
            return SignalLevel.InRepresentation(Value, (SignalLevel.LevelSpecification)cbo_Units.SelectedItem);
        }


        void cbo_Units_SelectedIndexChanged(object sender, EventArgs e)
        {
            try
            {
                _Level = _Level.ToRepresentation((SignalLevel.LevelSpecification)cbo_Units.SelectedItem);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            finally
            {
                RefreshControls();
            }
        }

        void SignalLevelCtrl_Resize(object sender, EventArgs e)
        {
            txt_Level.Location = new Point(0, 0);
            cbo_Units.Location = new Point(Width - cbo_Units.Width, 0);
            txt_Level.Width = cbo_Units.Left - 2;
            this.Height = cbo_Units.Height;
        }

        private void RefreshControls()
        {
            try
            {
                txt_Level.Text = Advent.aiLibrary.UnitsFormatter.FormatSigFigs(_Level.Value, 3, 4, true); 
                cbo_Units.SelectedItem = _Level.Specification;
            }
            catch { }
        }
    }
}
